home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume26 / tuner1.4 / part01 next >
Encoding:
Text File  |  1993-04-15  |  42.6 KB  |  1,621 lines

  1. Newsgroups: comp.sources.unix
  2. From: jack@cwi.nl (Jack Jansen)
  3. Subject: v26i164: tuner - a Motif-based utility for "radio" reception, Part01/01
  4. Sender: unix-sources-moderator@vix.com
  5. Approved: paul@vix.com
  6.  
  7. Submitted-By: jack@cwi.nl (Jack Jansen)
  8. Posting-Number: Volume 26, Issue 164
  9. Archive-Name: tuner1.4/part01
  10.  
  11. This is tuner version 1.4, a motif-based tuner to accompany the ethernet
  12. radio program, allowing you to select an ethernet radio station to listen
  13. to. It is meant to work with radio 2.0, but will also work with older
  14. releases of radio, although the playlist feature will not work.
  15.  
  16. "Radio" is a set of programs that allows you to connect an audio source
  17. (radio, CD player) to your Sun, SGI or NeXT workstation and broadcast low-fi
  18. (approximately AM radio quality) audio over a local area network. Other
  19. users can then listen to your broadcasts.
  20.  
  21. Radio is distributed separately, and is posted to comp.sources.unix around
  22. this time. It is also available for FTP access, as file /pub/radio2.0.tar.Z
  23. on host ftp.cwi.nl. This tuner is also available there, as
  24. /pub/tuner1.4.shar.
  25.  
  26.     Jack Jansen
  27.     Centrum voor Wiskunde en Informatica
  28.     Kruislaan 413
  29.     1098 SJ  Amsterdam
  30.     the Netherlands
  31.  
  32.     phone:    +31 20 592 4098
  33.     fax:      +31 20 592 4199
  34.     internet: jack@cwi.nl
  35.     X.400:    G=Jack;S=Jansen;O=cwi;P=surf;A=400net;C=nl
  36.  
  37. #! /bin/sh
  38. # This is a shell archive.  Remove anything before this line, then unpack
  39. # it by saving it into a file and typing "sh file".  To overwrite existing
  40. # files, type "sh file -c".  You can also feed this as standard input via
  41. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  42. # will see the following message at the end:
  43. #        "End of archive 1 (of 1)."
  44. # Contents:  MANIFEST Makefile README Tuner.resources customize.h
  45. #   tuner.h tuner.man tuner_io.c tuner_main.c tuner_sl.c tuner_ui.c
  46. #   tuner_volume.c
  47. # Wrapped by vixie@gw.home.vix.com on Thu Apr 15 18:45:50 1993
  48. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  49. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  50.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  51. else
  52. echo shar: Extracting \"'MANIFEST'\" \(486 characters\)
  53. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  54. X   File Name        Archive #    Description
  55. X-----------------------------------------------------------
  56. X MANIFEST                   1    This shipping list
  57. X Makefile                   1    
  58. X README                     1    
  59. X Tuner.resources            1    
  60. X customize.h                1    
  61. X tuner.h                    1    
  62. X tuner.man                  1    
  63. X tuner_io.c                 1    
  64. X tuner_main.c               1    
  65. X tuner_sl.c                 1    
  66. X tuner_ui.c                 1    
  67. X tuner_volume.c             1    
  68. END_OF_FILE
  69. if test 486 -ne `wc -c <'MANIFEST'`; then
  70.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  71. fi
  72. # end of 'MANIFEST'
  73. fi
  74. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  75.   echo shar: Will not clobber existing file \"'Makefile'\"
  76. else
  77. echo shar: Extracting \"'Makefile'\" \(1040 characters\)
  78. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  79. X#
  80. X# See file customize.h for additional customizations.
  81. X#
  82. X
  83. X# Customizations for SGI, Irix 4.0:
  84. MOTIF_INC=
  85. MOTIF_LIB=
  86. X
  87. RESDIR=/ufs/jack/etc
  88. BINDIR=/ufs/jack/bin/sgi
  89. X
  90. X#
  91. TUNERFLAGS=-I/share/usr/include -DVOLUME
  92. ALIB=-laudio
  93. X
  94. X#
  95. X# Customizations for Suns with old Motif in a funny place:
  96. X#MOTIF_INC=-DMOTIF1_0 -I/usr/local/X/usr/include/X11/motif
  97. X#MOTIF_LIB=-L/usr/local/X/motif/lib
  98. X
  99. RESDIR=/ufs/jack/etc
  100. BINDIR=/ufs/jack/bin/sgi
  101. X
  102. OBJS=tuner_main.o tuner_ui.o tuner_io.o tuner_sl.o tuner_volume.o
  103. SRCS=tuner_main.c tuner_io.c tuner_ui.c tuner_sl.c tuner_volume.c
  104. XXSRCS=README Makefile Tuner.resources tuner.man tuner.h customize.h
  105. CFLAGS=-O -DRESOURCE_PATH=\"$(RESDIR)/Tuner.resources\" $(MOTIF_INC) \
  106. X    $(TUNERFLAGS)
  107. X
  108. tuner: $(OBJS)
  109. X    $(CC) $(CFLAGS) $(OBJS) $(MOTIF_LIB) $(ALIB) -lXm -lXt -lX11 -lm -o tuner
  110. X
  111. X$(OBJS): tuner.h customize.h Makefile
  112. X
  113. install: tuner Tuner.resources
  114. X    cp tuner $(BINDIR)
  115. X    cp Tuner.resources $(RESDIR)
  116. X
  117. clean:
  118. X    rm -f $(OBJS)
  119. X
  120. shar:    tuner1.4.shar
  121. X
  122. tuner1.4.shar: $(XSRCS) $(SRCS)
  123. X    shar $(XSRCS) $(SRCS) > tuner1.4.shar
  124. END_OF_FILE
  125. if test 1040 -ne `wc -c <'Makefile'`; then
  126.     echo shar: \"'Makefile'\" unpacked with wrong size!
  127. fi
  128. # end of 'Makefile'
  129. fi
  130. if test -f 'README' -a "${1}" != "-c" ; then 
  131.   echo shar: Will not clobber existing file \"'README'\"
  132. else
  133. echo shar: Extracting \"'README'\" \(5108 characters\)
  134. sed "s/^X//" >'README' <<'END_OF_FILE'
  135. X    Tuner 1.4
  136. X    ---------
  137. X
  138. This is tuner version 1.4, a motif-based tuner to accompany the
  139. ethernet radio program, allowing you to select an ethernet radio
  140. station to listen to. It is meant to work with radio 2.0, but will
  141. also work with older releases of radio, although the playlist feature
  142. will not work.
  143. X
  144. X"Radio" is a set of programs that allows you to connect an audio
  145. source (radio, CD player) to your Sun, SGI or NeXT workstation and
  146. broadcast low-fi (approximately AM radio quality) audio over a local
  147. area network. Other users can then listen to your broadcasts.
  148. X
  149. Radio is distributed separately, and is posted to comp.sources.unix
  150. around this time. It is also available for FTP access, as file
  151. X/pub/radio2.0.tar.Z on host ftp.cwi.nl. This tuner is also available
  152. there, as /pub/tuner1.4.shar.
  153. X
  154. Differences with 1.3
  155. X--------------------
  156. X
  157. The only functionality that has been added since tuner 1.3 are the
  158. buttons to start radio and listen to the news.
  159. X
  160. Building tuner
  161. X--------------
  162. X
  163. Tuner has been tested on an SGI Iris Indigo running Irix 4.0.2 with
  164. Motif 1.1.
  165. X
  166. Version 1.3 also ran on a Sun Sparcstation running SunOS 4.1 with
  167. Motif 1.0, and I have no reasons to believe this will not work anymore.
  168. X
  169. The Motif 1.0 user interface has some quirks (updates of the
  170. X'playlist' list is an... uhm.... interesting process to watch:-) but
  171. it does work.
  172. X
  173. Before building tuner, the Makefile, customize.h and possibly
  174. Tuner.resources should be edited to reflect you local configuration.
  175. X
  176. X  The references to 'anp' need a little explanation. We have a service
  177. X  locally where we record the hourly newsbulletin from the radio and
  178. X  make it available to anyone at any time through the 'anp' program
  179. X  (named after the dutch newsservice). We do not distribute this stuff
  180. X  because it is both machine- and country-dependent (we recognize the
  181. X  news by doing FFTs on the audio and recognizing the leader tune).
  182. X
  183. X  If you want to implement a similar service and make it available
  184. X  through tuner the easiest way is to do is is:
  185. X  - find some way to put the news in a file every hour,
  186. X  - create a script with (roughly) the following contents:
  187. X     #!/bin/sh
  188. X     playaudio newsfile &
  189. X     echo $!
  190. X     wait
  191. X    where 'playaudio' is your audio player. Then set ANP_COMMAND in
  192. X    customize.h to the name of this script. The bit with echo and wait
  193. X    is meant to make it possible for tuner to abort the news.
  194. X
  195. In the Makefile, edit MOTIF_INC if you have Motif 1.0 (add option
  196. X-DMOTIF1_0) and/or if your motif include files live in a non-standard
  197. place (add option -I<include-path>).
  198. X
  199. Next, add an option -L<lib-path> to the MOTIF_LIB variable if your
  200. motif library (or X library, or Xt library) doesn't live in the
  201. standard library path.
  202. X
  203. XFinally, update the RESDIR and BINDIR variables to reflect in which
  204. directories you are going to keep the resource file and the tuner
  205. binary.
  206. X
  207. In the file customize.h you have to edit the DFT_NETS define. It should
  208. be set to all networks on which tuner should look for radio stations.
  209. XEdit the RADIO_COMMAND to something that starts radio on your system.
  210. XEdit ANP_COMMAND to start the newscast, or remove the definition if
  211. you do not want this feature.
  212. X
  213. You might have to edit Tuner.resources to change the default
  214. appearance of tuner. This will be the case if you use monochrome
  215. machines (tuner will not look very nice on a monochrome machine with
  216. the Tuner.resources file as distributed), if you don't have adobe
  217. fonts or if you want to use a language other than English.
  218. X
  219. You are now ready to 'make' and 'make install' to build and install tuner.
  220. X
  221. Notes
  222. X-----
  223. X
  224. Tuner is copyrighted but freely distributable. See the copyright
  225. notice below. If you make changes to tuner I would like to hear from you.
  226. X
  227. X    Jack Jansen
  228. X    Centrum voor Wiskunde en Informatica
  229. X    Kruislaan 413
  230. X    1098 SJ  Amsterdam
  231. X    the Netherlands
  232. X
  233. X    phone:    +31 20 592 4098
  234. X    fax:      +31 20 592 4199
  235. X    internet: jack@cwi.nl
  236. X    X.400:    G=Jack;S=Jansen;O=cwi;P=surf;A=400net;C=nl
  237. X
  238. X
  239. Copyright notice
  240. X----------------
  241. X
  242. Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum, Amsterdam, The
  243. Netherlands.
  244. X
  245. X                        All Rights Reserved
  246. X
  247. Permission to use, copy, modify, and distribute this software and its 
  248. documentation for any purpose and without fee is hereby granted, 
  249. provided that the above copyright notice appear in all copies and that
  250. both that copyright notice and this permission notice appear in 
  251. supporting documentation, and that the names of Stichting Mathematisch
  252. Centrum or CWI not be used in advertising or publicity pertaining to
  253. distribution of the software without specific, written prior permission.
  254. X
  255. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  256. THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  257. XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  258. XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  259. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  260. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  261. OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  262. END_OF_FILE
  263. if test 5108 -ne `wc -c <'README'`; then
  264.     echo shar: \"'README'\" unpacked with wrong size!
  265. fi
  266. # end of 'README'
  267. fi
  268. if test -f 'Tuner.resources' -a "${1}" != "-c" ; then 
  269.   echo shar: Will not clobber existing file \"'Tuner.resources'\"
  270. else
  271. echo shar: Extracting \"'Tuner.resources'\" \(4396 characters\)
  272. sed "s/^X//" >'Tuner.resources' <<'END_OF_FILE'
  273. X#
  274. X# Section one - Resources defining layout
  275. X#
  276. X
  277. Tuner*form.width:            600
  278. Tuner*form.height:            250
  279. X
  280. Tuner*topAttachment:            attach_position
  281. Tuner*bottomAttachment:            attach_position
  282. Tuner*leftAttachment:            attach_position
  283. Tuner*rightAttachment:            attach_position
  284. X
  285. Tuner*labelCurrent.topPosition:        1
  286. Tuner*labelCurrent.bottomPosition:    10
  287. Tuner*labelCurrent.leftPosition:    1
  288. Tuner*labelCurrent.rightPosition:    33
  289. X
  290. Tuner*labelPlaylist.topPosition:    1
  291. Tuner*labelPlaylist.bottomPosition:    10
  292. Tuner*labelPlaylist.leftPosition:    67
  293. Tuner*labelPlaylist.rightPosition:    99
  294. X
  295. Tuner*labelTuner.topPosition:        1
  296. Tuner*labelTuner.bottomPosition:    10
  297. Tuner*labelTuner.leftPosition:        34
  298. Tuner*labelTuner.rightPosition:        66
  299. X
  300. Tuner*stationF.topPosition:        11
  301. Tuner*stationF.bottomPosition:        21
  302. Tuner*stationF.leftPosition:        1
  303. Tuner*stationF.rightPosition:        33
  304. X
  305. Tuner*labelCurPlaying.topPosition:    22
  306. Tuner*labelCurPlaying.bottomPosition:    32
  307. Tuner*labelCurPlaying.leftPosition:    1
  308. Tuner*labelCurPlaying.rightPosition:    33
  309. X
  310. Tuner*playingF.topPosition:        33
  311. Tuner*playingF.bottomPosition:        43
  312. Tuner*playingF.leftPosition:        1
  313. Tuner*playingF.rightPosition:        33
  314. X
  315. Tuner*labelCurTime.topPosition:        44
  316. Tuner*labelCurTime.bottomPosition:    54
  317. Tuner*labelCurTime.leftPosition:    1
  318. Tuner*labelCurTime.rightPosition:    33
  319. X
  320. Tuner*timeF.topPosition:        55
  321. Tuner*timeF.bottomPosition:        65
  322. Tuner*timeF.leftPosition:        1
  323. Tuner*timeF.rightPosition:        33
  324. X
  325. Tuner*playlistSW.topPosition:        11
  326. Tuner*playlistSW.bottomPosition:    99
  327. Tuner*playlistSW.leftPosition:        67
  328. Tuner*playlistSW.rightPosition:        99
  329. X
  330. Tuner*tunerSW.topPosition:        11
  331. Tuner*tunerSW.bottomPosition:        89
  332. Tuner*tunerSW.leftPosition:        34
  333. Tuner*tunerSW.rightPosition:        66
  334. X
  335. Tuner*details.topPosition:        90
  336. Tuner*details.bottomPosition:        99
  337. Tuner*details.leftPosition:        1
  338. Tuner*details.rightPosition:        33
  339. X
  340. Tuner*labelVolume.topPosition:        66
  341. Tuner*labelVolume.bottomPosition:    76
  342. Tuner*labelVolume.leftPosition:        1
  343. Tuner*labelVolume.rightPosition:    9
  344. X
  345. Tuner*volume.topPosition:        66
  346. Tuner*volume.bottomPosition:        76
  347. Tuner*volume.leftPosition:        10
  348. Tuner*volume.rightPosition:        33
  349. Tuner*volume.orientation:        horizontal
  350. Tuner*volume.showArrows:        false
  351. Tuner*volume.minimum:            0
  352. Tuner*volume.maximum:            271
  353. Tuner*volume.sliderSize:        16
  354. X
  355. Tuner*mute.topPosition:            78
  356. Tuner*mute.bottomPosition:        88
  357. Tuner*mute.leftPosition:        1
  358. Tuner*mute.rightPosition:        16
  359. X
  360. Tuner*radio.topPosition:        78
  361. Tuner*radio.bottomPosition:        88
  362. Tuner*radio.leftPosition:        17
  363. Tuner*radio.rightPosition:        33
  364. X
  365. Tuner*revert.topPosition:        90
  366. Tuner*revert.bottomPosition:        99
  367. Tuner*revert.leftPosition:        34
  368. Tuner*revert.rightPosition:        66
  369. X
  370. Tuner*OK.topPosition:            89
  371. Tuner*OK.bottomPosition:        99
  372. Tuner*OK.leftPosition:            1
  373. Tuner*OK.rightPosition:            16
  374. X
  375. Tuner*anp.topPosition:            89
  376. Tuner*anp.bottomPosition:        99
  377. Tuner*anp.leftPosition:            17
  378. Tuner*anp.rightPosition:        33
  379. X
  380. Tuner*shadowThickness:            2
  381. Tuner*XmFrame.shadowType:        shadow_in
  382. X
  383. X#
  384. X# Section 2 - Resources defining labels
  385. X#
  386. Tuner*labelCurrent.labelString:     Current station:
  387. Tuner*labelCurPlaying.labelString:    Playing:
  388. Tuner*labelCurTime.labelString:        Since:
  389. Tuner*labelPlaylist.labelString:    Playlist:
  390. Tuner*labelTuner.labelString:        Choose new station:
  391. Tuner*labelVolume.labelString:        Vol:
  392. X
  393. Tuner*mute.labelString:            Mute
  394. Tuner*revert.labelString:        Previous
  395. Tuner*OK.labelString:            Exit
  396. Tuner*radio.labelString:        Start radio
  397. Tuner*anp.labelString:            ANP
  398. X
  399. X#
  400. X# Section 3 - Resources defining colors used.
  401. X#
  402. X# Scheme used: one color for 'select things', one for 'current station things',
  403. X# one for 'new station things', one for background.
  404. X# playlist color is selected from tuner highlight or station color.
  405. X#
  406. Tuner*background:            grey70
  407. Tuner*foreground:            black
  408. Tuner*labelCurrent.foreground:        blue
  409. Tuner*labelTuner.foreground:        green
  410. X
  411. Tuner*playlist.background:        grey80
  412. Tuner*playing.background:        grey80
  413. Tuner*station.background:        grey80
  414. Tuner*time.background:            grey80
  415. Tuner*volume.background:        grey80
  416. X
  417. X#
  418. X# Section 4 - Fonts used.
  419. X#
  420. Tuner*XmPushButton*fontList:        -adobe-courier-bold-r-*--10-*
  421. Tuner*XmToggleButton*fontList:        -adobe-courier-bold-r-*--10-*
  422. Tuner*XmLabel*fontList:            -adobe-courier-bold-o-*--14-*
  423. Tuner*station*fontList:            -adobe-courier-medium-r-*--10-*
  424. Tuner*playing*fontList:            -adobe-courier-medium-r-*--10-*
  425. Tuner*time*fontList:            -adobe-courier-medium-r-*--10-*
  426. Tuner*tuner*fontList:            -adobe-courier-bold-r-*--10-*
  427. Tuner*playlist*fontList:        -adobe-helvetica-medium-r-*--8-*
  428. END_OF_FILE
  429. if test 4396 -ne `wc -c <'Tuner.resources'`; then
  430.     echo shar: \"'Tuner.resources'\" unpacked with wrong size!
  431. fi
  432. # end of 'Tuner.resources'
  433. fi
  434. if test -f 'customize.h' -a "${1}" != "-c" ; then 
  435.   echo shar: Will not clobber existing file \"'customize.h'\"
  436. else
  437. echo shar: Extracting \"'customize.h'\" \(898 characters\)
  438. sed "s/^X//" >'customize.h' <<'END_OF_FILE'
  439. X
  440. X/*
  441. X** Where the default resources are.
  442. X*/
  443. X#ifndef RESOURCE_PATH
  444. X#define RESOURCE_PATH    "./Tuner.resources"
  445. X#endif
  446. X
  447. X/*
  448. X** Max number of broadcast nets searched, radio stations and
  449. X** records listed in playlist.
  450. X*/
  451. X#define MAXNET 5        /* Maximum number of networks to poll */
  452. X#define MAXSTATION 20        /* Maximum number of stations */
  453. X#define MAXPLBUF 100        /* Keep 100 last tracks */
  454. X#define MAXNAME 64        /* Max size of all sorts of names */
  455. X
  456. X/*
  457. X** Networks on which to look for radio stations
  458. X*/
  459. X#define DFT_NETS    "192.16.184.0", "192.16.191.0", "192.16.201.255"
  460. X
  461. X/*
  462. X** Control ports for transmitter and radio programs.
  463. X*/
  464. X#define CTLPRT_SCALL    54317
  465. X#define CTLPRT_XMIT    54319
  466. X#define CTLPRT_RADIO    54320
  467. X
  468. X/*
  469. X** Timeout (in seconds) waiting for replies to station locate broadcast
  470. X*/
  471. X#define WAIT_TIMEOUT    2
  472. X
  473. X#define RADIO_COMMAND    "/usr/local/radio/bin/radio &"
  474. X#define ANP_COMMAND    "/ufs/jack/bin/sgi/anp -p"
  475. END_OF_FILE
  476. if test 898 -ne `wc -c <'customize.h'`; then
  477.     echo shar: \"'customize.h'\" unpacked with wrong size!
  478. fi
  479. # end of 'customize.h'
  480. fi
  481. if test -f 'tuner.h' -a "${1}" != "-c" ; then 
  482.   echo shar: Will not clobber existing file \"'tuner.h'\"
  483. else
  484. echo shar: Extracting \"'tuner.h'\" \(1620 characters\)
  485. sed "s/^X//" >'tuner.h' <<'END_OF_FILE'
  486. X#include <X11/Intrinsic.h>
  487. X#include <Xm/Xm.h>
  488. X
  489. X#include "customize.h"
  490. X
  491. X#ifdef __STDC__
  492. X#define ARGS(x) x
  493. X#else
  494. X#define ARGS(x) ()
  495. X#define void int
  496. X#endif
  497. X
  498. X#ifndef GLOBAL
  499. X#define GLOBAL extern
  500. X#endif /* GLOBAL */
  501. X
  502. GLOBAL int cur_tune;                    /* From tuner_io */
  503. X
  504. GLOBAL Widget toplevel;                             /* Main widget */
  505. X
  506. GLOBAL Widget form;                       /* The form */
  507. X
  508. GLOBAL Widget currentStation, currentPlaying, currentTime; /* current station info */
  509. GLOBAL Widget playlistBrowser;                             /* cur playlist */
  510. GLOBAL Widget tunerBrowser;                                /* station selector */
  511. GLOBAL Widget muteButton;                                  /* The buttons */
  512. GLOBAL Widget detailsButton;
  513. GLOBAL Widget revertButton;
  514. GLOBAL Widget listenButton;
  515. GLOBAL Widget okButton;
  516. GLOBAL Widget radioButton;
  517. X#ifdef ANP_COMMAND
  518. GLOBAL Widget anpButton;
  519. X#endif /* ANP_COMMAND */
  520. X#ifdef VOLUME
  521. GLOBAL Widget volumeSlider;
  522. GLOBAL Widget labelVolume;
  523. X#endif /* VOLUME */
  524. X
  525. GLOBAL Widget labelCurrent, labelTuner, labelPlaylist;
  526. X
  527. GLOBAL XmString *tunerData;
  528. X
  529. GLOBAL XmString *playlistData;                             /* The playlist */
  530. GLOBAL int playlistDataN;
  531. X
  532. GLOBAL int origstation;
  533. X
  534. X/* From tuner_main.c */
  535. void do_tune ARGS((int));
  536. void do_mute ARGS((int));
  537. void do_revert ARGS((void));
  538. X
  539. X/* From tuner_ui.c */
  540. void init_ui ARGS((int *, char **));
  541. void show_tune ARGS((int, char *, char *, char *, int));
  542. void show_tuner ARGS((char **, int));
  543. void show_playlist ARGS((char **, int, int));
  544. X
  545. X/* From tuner_io.c */
  546. void sendsock ARGS((int, struct sockaddr_in *, char *));
  547. char *recvsock ARGS((int));
  548. END_OF_FILE
  549. if test 1620 -ne `wc -c <'tuner.h'`; then
  550.     echo shar: \"'tuner.h'\" unpacked with wrong size!
  551. fi
  552. # end of 'tuner.h'
  553. fi
  554. if test -f 'tuner.man' -a "${1}" != "-c" ; then 
  555.   echo shar: Will not clobber existing file \"'tuner.man'\"
  556. else
  557. echo shar: Extracting \"'tuner.man'\" \(1909 characters\)
  558. sed "s/^X//" >'tuner.man' <<'END_OF_FILE'
  559. X.TH TUNER 1 "28 Jan 1993
  560. X.SH NAME
  561. X.B tuner
  562. X- A motif-based tuner for ethernet radio stations
  563. X.SH SYNOPSIS
  564. X.B tuner
  565. X.SH DESCRIPTION
  566. Tuner is used in conjunction with
  567. X.IR radio (1)
  568. and
  569. X.IR transmitter (1),
  570. the CWI ethernet radio software. It allows you to browse through the
  571. available radio stations and their playlists and to select one to
  572. listen to.
  573. X.LP
  574. The window shows the name of the station you are currently listening
  575. to, what it is playing and since when, a list of stations that are
  576. currently in the air and the playlist of the current station (i.e. the
  577. most recent 100 records played), if available.
  578. If you select a new station in the
  579. station browser the playlist browser will tune your radio to the selected
  580. station. This also updates the playlist display.
  581. When new stations come on the air or when the currently tuned
  582. station changes records the display is updated accordingly.
  583. X.LP
  584. The
  585. X.I `mute'
  586. toggle sends a message to the radio program asking it to shut up (or,
  587. if it is already muted, to continue playing).
  588. X.LP
  589. The
  590. X.I `revert'
  591. button sets the station back to what it originally was.
  592. X.LP
  593. The
  594. X.I `OK'
  595. button exits tuner.
  596. X.LP
  597. The
  598. X.I `radio'
  599. button attempts to start a radio program. No check is made whether a
  600. radio program is already running, so use with care.
  601. X.LP
  602. If stored newsbulletins are available on your system the
  603. X.I `anp'
  604. button will play the most recent news bulletin.
  605. X.LP
  606. If you are using an SGI a volume slider will allow you to control the
  607. output volume.
  608. X
  609. X.LP
  610. The program uses an X resource file to control many aspects of its
  611. appearance and behaviour, so you can change quite a few things to suit
  612. your needs. This might especially be useful for monochrome displays,
  613. since the default resources are tuned for color machines.
  614. X.SH BUGS
  615. Under Motif 1.0 updating the playlist looks weird.
  616. X.SH "SEE ALSO"
  617. radio(1), newcd(1), broadcast(1)
  618. X.SH "AUTHOR"
  619. Jack Jansen, CWI, Jack.Jansen@cwi.nl
  620. END_OF_FILE
  621. if test 1909 -ne `wc -c <'tuner.man'`; then
  622.     echo shar: \"'tuner.man'\" unpacked with wrong size!
  623. fi
  624. # end of 'tuner.man'
  625. fi
  626. if test -f 'tuner_io.c' -a "${1}" != "-c" ; then 
  627.   echo shar: Will not clobber existing file \"'tuner_io.c'\"
  628. else
  629. echo shar: Extracting \"'tuner_io.c'\" \(7883 characters\)
  630. sed "s/^X//" >'tuner_io.c' <<'END_OF_FILE'
  631. X#include <stdio.h>
  632. X#include <sys/types.h>
  633. X#include <sys/socket.h>
  634. X#include <sys/time.h>
  635. X#include <netinet/in.h>
  636. X#include <netdb.h>
  637. X#include <sys/stat.h>
  638. X
  639. X#ifndef INADDR_NONE
  640. X#define INADDR_NONE -1
  641. X#endif
  642. X
  643. X#include "tuner.h"
  644. X
  645. static do_stationcall();
  646. X
  647. char *dft_nets[] = { DFT_NETS, 0 };
  648. X
  649. char radio_host[64];        /* Host where radio runs */
  650. X
  651. int transmitter_port = CTLPRT_XMIT;    /* Default control port for transmitters */
  652. int radio_port = CTLPRT_RADIO;        /* Default control port for radios */
  653. struct sockaddr_in radio_addr;    /* Address of our radio */
  654. struct sockaddr_in bcast_addrs[MAXNET];    /* Addresses of transmitters */
  655. int num_bcast_addrs = 0;
  656. X
  657. struct station_info {
  658. X    char name[MAXNAME];        /* station name */
  659. X    int port;            /* UDP broadcast port */
  660. X    int is_playing;        /* 1 if currently transmitting */
  661. X    char logfile[MAXNAME];    /* Name of cdlog file */
  662. X    int since;            /* Play time in minutes of current CD */
  663. X    char cdname[MAXNAME];    /* Current CD name */
  664. X};
  665. X
  666. struct station_info stations[MAXSTATION];
  667. X
  668. char *station_names[MAXSTATION];    /* Hack. Points into stations array */
  669. int num_stations;
  670. X
  671. char cur_name[MAXNAME];
  672. char cur_play[MAXNAME];
  673. char cur_time[MAXNAME];
  674. int cur_mute;
  675. int cur_port;
  676. int origtune = -1;
  677. X
  678. int sock;            /* Our socket */
  679. int sc_sock;            /* Stationcall socket */
  680. X
  681. char plbuf[MAXPLBUF][MAXNAME];
  682. char *playlist[MAXPLBUF];
  683. int num_playlist;
  684. X
  685. init_io() {
  686. X    struct hostent *hent;
  687. X    int i;
  688. X
  689. X    for( i=0; i<MAXSTATION; i++)
  690. X      station_names[i] = stations[i].name;
  691. X    /*XXX Process args */
  692. X    sock = opensock();
  693. X    sc_sock = openscsock();
  694. X
  695. X    /*
  696. X    ** Divine address struct for radio station we're controlling.
  697. X    */
  698. X    if ( radio_host[0] == 0 ) {
  699. X    if ( gethostname(radio_host, sizeof(radio_host)) < 0 ) {
  700. X        perror("gethostname");
  701. X        exit(1);
  702. X    }
  703. X    }
  704. X    if ( (hent=gethostbyname(radio_host)) == 0 ) {
  705. X#ifndef sun
  706. X    herror(radio_host);
  707. X#else
  708. X    fprintf(stderr, "%s: Unknown host name\n", radio_host);
  709. X#endif
  710. X    exit(1);
  711. X    }
  712. X    radio_addr.sin_family = AF_INET;
  713. X    radio_addr.sin_port = htons(radio_port);
  714. X    memcpy(&radio_addr.sin_addr, hent->h_addr, hent->h_length);
  715. X    /*
  716. X    ** Create list of broadcast addresses for locating stations.
  717. X    */
  718. X    if ( num_bcast_addrs == 0 ) {
  719. X    /*
  720. X    ** No addresses in arguments. Do the defaults.
  721. X    */
  722. X    char **p;
  723. X
  724. X    for( p=dft_nets; *p; p++ )
  725. X      add_bcast_addr(*p);
  726. X    }
  727. X    /*
  728. X    ** Obtain station info and current station.
  729. X    */
  730. X    get_stations();
  731. X    get_curinfo();
  732. X    origstation = cur_tune;
  733. X    show_tuner(station_names, num_stations);
  734. X    show_tune(cur_tune, cur_name, cur_play, cur_time, cur_mute);
  735. X    show_playlist(playlist, num_playlist,1);
  736. X    watch_socket(sc_sock, do_stationcall);
  737. X}
  738. X
  739. get_stations() {
  740. X    int i;
  741. X    char *s;
  742. X    struct station_info *p;
  743. X
  744. X    /*
  745. X    ** Clear old stations.
  746. X    */
  747. X    num_stations = 0;
  748. X    /*
  749. X    ** Broadcast info request.
  750. X    */
  751. X    for(i=0; i<num_bcast_addrs; i++)
  752. X      sendsock(sock, &bcast_addrs[i], "radio:s");
  753. X    /*
  754. X    ** Receive replies.
  755. X    */
  756. X    while ( (s=recvsock(sock)) ) {
  757. X    p = stations + num_stations;
  758. X    if ( parse_stationcall(p, s) )
  759. X      num_stations++;
  760. X    }
  761. X}
  762. X
  763. static
  764. do_stationcall(d1, d2, d3)
  765. X    int d1, d2, d3;
  766. X{
  767. X    char *s;
  768. X    struct station_info sistr;
  769. X    int i;
  770. X
  771. X    if ( (s=recvsock(sc_sock)) == NULL ) {
  772. X    fprintf(stderr, "tuner: stationcall event without data?\n");
  773. X    return;
  774. X    }
  775. X    if ( !parse_stationcall(&sistr, s) )
  776. X      return;
  777. X    for ( i=0; i<num_stations; i++)
  778. X      if ( stations[i].port == sistr.port ) {
  779. X      stations[i] = sistr;
  780. X      if ( sistr.port == cur_port ) {
  781. X          if( get_curinfo() )
  782. X        show_playlist(playlist, num_playlist,1);
  783. X          show_tune(cur_tune, cur_name, cur_play, cur_time, cur_mute);
  784. X      }
  785. X      return;
  786. X      }
  787. X    stations[num_stations] = sistr;
  788. X    num_stations++;
  789. X    show_tuner(station_names, num_stations);
  790. X}
  791. X    
  792. parse_stationcall(p, s)
  793. X    struct station_info *p;
  794. X    char *s;
  795. X{
  796. X    int port;
  797. X    char name[MAXNAME], logname[MAXNAME], cdname[MAXNAME];
  798. X    int is_playing, since;
  799. X    int i;
  800. X
  801. X    is_playing = 1;
  802. X    since = -1;
  803. X    cdname[0] = '\0';
  804. X    logname[0] = '\0';
  805. X    i = sscanf(s, "radio:S:%[^:]:%d:%d:%[^:]:%d:%[^\n]", name, &port,
  806. X           &is_playing, logname, &since, cdname);
  807. X    if ( i >= 2 ) {
  808. X    strncpy(p->name, name, MAXNAME);
  809. X    p->port = port;
  810. X    p->is_playing = is_playing;
  811. X    strncpy(p->logfile, logname, MAXNAME);
  812. X    p->since = since;
  813. X    strncpy(p->cdname, cdname, MAXNAME);
  814. X    return 1;
  815. X    }
  816. X    fprintf(stderr, "Ill-formatted station call(%d): '%s'\n",i,  s);
  817. X    return 0;
  818. X}
  819. X
  820. add_bcast_addr(addr)
  821. X    char *addr;
  822. X{
  823. X    struct sockaddr_in *sp;
  824. X    unsigned long iaddr;
  825. X
  826. X    sp = &bcast_addrs[num_bcast_addrs++];
  827. X    if ( (iaddr=inet_addr(addr)) == INADDR_NONE) {
  828. X    fprintf(stderr, "Ill-formatted address %s\n", addr);
  829. X    exit(1);
  830. X    }
  831. X    
  832. X    sp->sin_family = AF_INET;
  833. X    sp->sin_addr.s_addr = iaddr;
  834. X    sp->sin_port = htons(transmitter_port);
  835. X}
  836. X
  837. get_curinfo() {
  838. X    char *s;
  839. X    int n;
  840. X    int port, muteoff;
  841. X    int i;
  842. X    FILE *fp;
  843. X    char buf[128];
  844. X    int t;
  845. X
  846. X    sendsock(sock, &radio_addr, "radio:i");
  847. X    num_playlist = 0;
  848. X    if ( s = recvsock(sock) ) {
  849. X    /*
  850. X    ** Parsing is funny, because older radio programs didn't have the
  851. X    ** mute feature (so only send a single number, the port).
  852. X    */
  853. X    n = sscanf(s, "radio:I:%d:%d", &muteoff, &port);
  854. X    if ( n == 0 ) {
  855. X        fprintf(stderr, "Funny reply from radio program: %s\n", s);
  856. X        return 1;
  857. X    }
  858. X    if ( n == 1 ) {
  859. X        port = muteoff;
  860. X        muteoff = 1;
  861. X    }
  862. X    cur_mute = !muteoff;
  863. X    cur_port = port;
  864. X    /*
  865. X    ** Try to find the corresponding station
  866. X    */
  867. X    for(i=0; i<num_stations; i++) {
  868. X        if ( cur_port == stations[i].port ) {
  869. X        cur_tune = i+1;
  870. X        strcpy(cur_name, stations[i].name);
  871. X        strcpy(cur_play, stations[i].cdname);
  872. X        t = stations[i].since / 60;
  873. X        if ( t == 0 )
  874. X          cur_time[0] = '\0';
  875. X        else if ( t < 60 )
  876. X          sprintf(cur_time, "%d minutes", t);
  877. X        else
  878. X          sprintf(cur_time, "%d hours", t/60);
  879. X        if ( !stations[i].is_playing )
  880. X          strcat(cur_time, "(Silent)");
  881. X        if ( stations[i].logfile[0] )
  882. X          return get_playlist(stations[i].logfile);
  883. X        return 1;
  884. X        }
  885. X    }
  886. X    if ( i == num_stations ) {
  887. X        /* Couldn't find the station number */
  888. X        cur_tune = 0;
  889. X        sprintf(cur_name, "Unknown (port %d)", cur_port);
  890. X        strcpy(cur_play, "?");
  891. X        strcpy(cur_time, "?");
  892. X        return 1;
  893. X    }
  894. X    }
  895. X    fprintf(stderr, "Warning: radio program not responding\n");
  896. X    strcpy(cur_name, "?");
  897. X    strcpy(cur_time, "?");
  898. X    strcpy(cur_play, "?");
  899. X    cur_tune = 0;
  900. X    return 1;
  901. X}
  902. X
  903. void
  904. do_tune(station)
  905. X    int station;
  906. X{
  907. X    char buf[32];
  908. X
  909. X    if ( station == 0 ) return;
  910. X    sprintf(buf, "radio:t:%d", stations[station-1].port);
  911. X    sendsock(sock, &radio_addr, buf);
  912. X    get_curinfo();
  913. X    show_tune(cur_tune, cur_name, cur_play, cur_time, cur_mute);
  914. X    show_playlist(playlist, num_playlist,1);
  915. X}
  916. X
  917. X/*
  918. X** do_mute - Mute radio
  919. X*/
  920. void
  921. do_mute(onoff)
  922. X    int onoff;
  923. X{
  924. X    sendsock(sock, &radio_addr, onoff?"radio:0":"radio:1");
  925. X}
  926. X
  927. X/*
  928. X** get last MAXPLBUF entries of playlist file.
  929. X*/
  930. get_playlist(file)
  931. X    char *file;
  932. X{
  933. X    FILE *fp;
  934. X    int i, j;
  935. X    static char fnbuf[MAXNAME];
  936. X    struct stat sb;
  937. X    static int mtime, saved_num_playlist;
  938. X
  939. X    if ( strncmp(file, fnbuf, MAXNAME) == 0 ) {
  940. X    if ( stat(file, &sb) >= 0 && sb.st_mtime == mtime ) {
  941. X        /* Yes, cached copy still ok */
  942. X        num_playlist = saved_num_playlist;
  943. X        return 0;
  944. X    }
  945. X    }
  946. X
  947. X    if ( (fp=fopen(file, "r")) == 0 )
  948. X      return;
  949. X
  950. X    strncpy(fnbuf, file, MAXNAME);
  951. X    stat(file, &sb);
  952. X    mtime = sb.st_mtime;
  953. X
  954. X    i = 0;
  955. X    while( (fgets(plbuf[i%MAXPLBUF], MAXNAME, fp)) ) i++;
  956. X    if ( i == 0 ) {
  957. X    num_playlist = 0;
  958. X    saved_num_playlist = 0;
  959. X    return;
  960. X    }
  961. X    i--;
  962. X
  963. X    if ( i < MAXPLBUF ) {
  964. X    num_playlist = i+1;
  965. X    while ( i >= 0 ) {
  966. X        playlist[i] = plbuf[i];
  967. X        i--;
  968. X    }
  969. X    }
  970. X    else {
  971. X    for ( j=0; j<MAXPLBUF; j++) playlist[j] = plbuf[(i+j+1) % MAXPLBUF];
  972. X    num_playlist = MAXPLBUF;
  973. X    }
  974. X    saved_num_playlist = num_playlist;
  975. X    fclose(fp);
  976. X    return 1;
  977. X}
  978. END_OF_FILE
  979. if test 7883 -ne `wc -c <'tuner_io.c'`; then
  980.     echo shar: \"'tuner_io.c'\" unpacked with wrong size!
  981. fi
  982. # end of 'tuner_io.c'
  983. fi
  984. if test -f 'tuner_main.c' -a "${1}" != "-c" ; then 
  985.   echo shar: Will not clobber existing file \"'tuner_main.c'\"
  986. else
  987. echo shar: Extracting \"'tuner_main.c'\" \(514 characters\)
  988. sed "s/^X//" >'tuner_main.c' <<'END_OF_FILE'
  989. X#include <stdio.h>
  990. X
  991. X#define GLOBAL
  992. X#include "tuner.h"
  993. X
  994. char *getenv();
  995. X
  996. main(argc, argv)
  997. X    int argc;
  998. X    char **argv;
  999. X{
  1000. X
  1001. X    if ( getenv("XENVIRONMENT") == 0 )
  1002. X#ifdef __STDC__
  1003. X      putenv("XENVIRONMENT=" RESOURCE_PATH);
  1004. X#else
  1005. X      putenv(strcat("XENVIRONMENT=", RESOURCE_PATH));
  1006. X#endif
  1007. X    
  1008. X    init_ui(&argc, argv);
  1009. X
  1010. X    init_io(&argc, argv);
  1011. X
  1012. X    if ( argc != 1 ) {
  1013. X    fprintf(stderr, "%s: Warning: extraneous args ignored\n", argv[0]);
  1014. X    exit(1);
  1015. X    }
  1016. X    
  1017. X    XtRealizeWidget(toplevel);
  1018. X
  1019. X    XtMainLoop();
  1020. X}
  1021. END_OF_FILE
  1022. if test 514 -ne `wc -c <'tuner_main.c'`; then
  1023.     echo shar: \"'tuner_main.c'\" unpacked with wrong size!
  1024. fi
  1025. # end of 'tuner_main.c'
  1026. fi
  1027. if test -f 'tuner_sl.c' -a "${1}" != "-c" ; then 
  1028.   echo shar: Will not clobber existing file \"'tuner_sl.c'\"
  1029. else
  1030. echo shar: Extracting \"'tuner_sl.c'\" \(2957 characters\)
  1031. sed "s/^X//" >'tuner_sl.c' <<'END_OF_FILE'
  1032. X/***********************************************************
  1033. Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
  1034. Netherlands.
  1035. X
  1036. X                        All Rights Reserved
  1037. X
  1038. Permission to use, copy, modify, and distribute this software and its 
  1039. documentation for any purpose and without fee is hereby granted, 
  1040. provided that the above copyright notice appear in all copies and that
  1041. both that copyright notice and this permission notice appear in 
  1042. supporting documentation, and that the names of Stichting Mathematisch
  1043. Centrum or CWI not be used in advertising or publicity pertaining to
  1044. distribution of the software without specific, written prior permission.
  1045. X
  1046. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  1047. THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  1048. XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  1049. XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  1050. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  1051. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  1052. OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  1053. X
  1054. X******************************************************************/
  1055. X
  1056. X/* Socket-related subroutines shared by broadcast and radio */
  1057. X
  1058. X#include <stdio.h>
  1059. X#include <errno.h>
  1060. X#include <stdlib.h>
  1061. X#include <fcntl.h>
  1062. X#include <netdb.h>
  1063. X
  1064. X#include <sys/types.h>
  1065. X#include <sys/socket.h>
  1066. X#include <sys/time.h>
  1067. X#include <netinet/in.h>
  1068. X
  1069. X#include "tuner.h"
  1070. X
  1071. X#define MSG_BUFSIZE 128                /* Message size */
  1072. X
  1073. int
  1074. opensock()
  1075. X{
  1076. X    int s;
  1077. X    int on = 1;
  1078. X
  1079. X    s = socket(AF_INET, SOCK_DGRAM, 0);
  1080. X    if (s < 0) {
  1081. X        perror("socket()");
  1082. X        exit(1);
  1083. X    }
  1084. X
  1085. X    if (setsockopt(s, SOL_SOCKET, SO_BROADCAST,
  1086. X            &on, sizeof (on)) < 0) {
  1087. X        perror("setsockopt(SO_BROADCAST)");
  1088. X        exit(1);
  1089. X    }
  1090. X    return s;
  1091. X}
  1092. X
  1093. int
  1094. openscsock()
  1095. X{
  1096. X    int s;
  1097. X    int on = 1;
  1098. X    struct sockaddr_in sin;
  1099. X
  1100. X    s = socket(AF_INET, SOCK_DGRAM, 0);
  1101. X#ifdef SO_REUSEPORT
  1102. X    (void)setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
  1103. X#endif
  1104. X    bzero((char *)&sin, sizeof sin);
  1105. X    sin.sin_addr.s_addr = INADDR_ANY;
  1106. X    sin.sin_family = AF_INET;
  1107. X    sin.sin_port = htons(CTLPRT_SCALL);
  1108. X    if ( bind(s, &sin, sizeof sin) < 0) {
  1109. X    perror("bind(stationcallsocket)");
  1110. X    exit(1);
  1111. X    }
  1112. X    return s;
  1113. X}
  1114. X
  1115. char *
  1116. recvsock(s)
  1117. X    int s;
  1118. X{
  1119. X    fd_set fdset;
  1120. X    int rv;
  1121. X    struct timeval tv;
  1122. X    static char buf[MSG_BUFSIZE];
  1123. X
  1124. X    FD_ZERO(&fdset);
  1125. X    FD_SET(s, &fdset);
  1126. X    tv.tv_sec = WAIT_TIMEOUT;
  1127. X    tv.tv_usec = 0;
  1128. X    if( (rv = select(s+1, &fdset, (fd_set *)0, (fd_set *)0, &tv)) < 0 ) {
  1129. X    perror("select(socket)");
  1130. X    exit(1);
  1131. X    }
  1132. X    if ( rv == 0 )
  1133. X      return NULL;
  1134. X    if ( (rv=recv(s, buf, sizeof(buf), 0)) < 0 ) {
  1135. X    perror("recv()");
  1136. X    exit(1);
  1137. X    }
  1138. X    buf[rv] = 0;
  1139. X    return buf;
  1140. X}
  1141. X  
  1142. X
  1143. void
  1144. sendsock(s, to, msg)
  1145. X    int s;
  1146. X    struct sockaddr_in *to;
  1147. X    char *msg;
  1148. X{
  1149. X    if ( sendto(s, msg, strlen(msg), 0, to, sizeof(*to)) < 0 ) {
  1150. X    perror("sendto()");
  1151. X    exit(1);
  1152. X    }
  1153. X}
  1154. END_OF_FILE
  1155. if test 2957 -ne `wc -c <'tuner_sl.c'`; then
  1156.     echo shar: \"'tuner_sl.c'\" unpacked with wrong size!
  1157. fi
  1158. # end of 'tuner_sl.c'
  1159. fi
  1160. if test -f 'tuner_ui.c' -a "${1}" != "-c" ; then 
  1161.   echo shar: Will not clobber existing file \"'tuner_ui.c'\"
  1162. else
  1163. echo shar: Extracting \"'tuner_ui.c'\" \(8557 characters\)
  1164. sed "s/^X//" >'tuner_ui.c' <<'END_OF_FILE'
  1165. X#include <stdio.h>
  1166. X#include <sys/types.h>
  1167. X#include <signal.h>
  1168. X#include <Xm/Label.h>
  1169. X#include <Xm/PushB.h>
  1170. X#include <Xm/ToggleB.h>
  1171. X#include <Xm/MainW.h>
  1172. X#include <Xm/List.h>
  1173. X#include <Xm/Form.h>
  1174. X#include <Xm/RowColumn.h>
  1175. X#include <Xm/Separator.h>
  1176. X#include <Xm/Frame.h>
  1177. X#include <Xm/ScrollBar.h>
  1178. X
  1179. X#include "tuner.h"
  1180. X
  1181. X#define LABEL(args, n, name, parent) \
  1182. X  XtCreateManagedWidget(name, xmLabelWidgetClass, parent, NULL, 0)
  1183. X
  1184. static void cb_tuner(), cb_mute(), cb_details(), cb_revert(), cb_ok(),
  1185. X  cb_playlist(), cb_radio();
  1186. X#ifdef ANP_COMMAND
  1187. static void cb_anp();
  1188. X#endif /* ANP_COMMAND */
  1189. X#ifdef VOLUME
  1190. static void cb_volume();
  1191. X#endif /* VOLUME */
  1192. X
  1193. int initialized;
  1194. char *kept_message;        /* Message to be displayed after init */
  1195. X
  1196. int tuner_pos = 0, prev_pos = 0;
  1197. X
  1198. void
  1199. init_ui(argcp, argv)
  1200. X    int *argcp;
  1201. X    char **argv;
  1202. X{
  1203. X    Arg args[20];
  1204. X    int n = 0;
  1205. X    XmString str1;
  1206. X    char str[100];
  1207. X    int i;
  1208. X
  1209. X    toplevel = XtInitialize(argv[0], "Tuner", NULL, 0, argcp, argv);
  1210. X
  1211. X    n = 0;
  1212. X    form = XtCreateManagedWidget("form", xmFormWidgetClass,
  1213. X                toplevel, args, n);
  1214. X
  1215. X    labelCurrent = LABEL(args, n, "labelCurrent", form);
  1216. X
  1217. X    n = 0;
  1218. X    currentStation = XtCreateManagedWidget("stationF", xmFrameWidgetClass,
  1219. X                       form, args, n);
  1220. X    
  1221. X    n = 0;
  1222. X    currentStation = XtCreateManagedWidget("station", xmLabelWidgetClass,
  1223. X                       currentStation, args, n);
  1224. X
  1225. X    (void)LABEL(args, n, "labelCurPlaying", form);
  1226. X
  1227. X    n = 0;
  1228. X    currentPlaying = XtCreateManagedWidget("playingF", xmFrameWidgetClass,
  1229. X                       form, args, n);
  1230. X    
  1231. X    n = 0;
  1232. X    currentPlaying = XtCreateManagedWidget("playing", xmLabelWidgetClass,
  1233. X                       currentPlaying, args, n);
  1234. X
  1235. X    (void)LABEL(args, n, "labelCurTime", form);
  1236. X
  1237. X    n = 0;
  1238. X    currentTime = XtCreateManagedWidget("timeF", xmFrameWidgetClass,
  1239. X                       form, args, n);
  1240. X    
  1241. X    n = 0;
  1242. X    currentTime = XtCreateManagedWidget("time", xmLabelWidgetClass,
  1243. X                    currentTime, args, n);
  1244. X    
  1245. X    labelPlaylist = LABEL(args, n, "labelPlaylist", form);
  1246. X    
  1247. X    n = 0;
  1248. X    playlistBrowser = XmCreateScrolledList(form, "playlist", args, n);
  1249. X    XtAddCallback(playlistBrowser, XmNbrowseSelectionCallback, cb_playlist, 0);
  1250. X    XtManageChild(playlistBrowser);
  1251. X
  1252. X    labelTuner = LABEL(args, n, "labelTuner", form);
  1253. X
  1254. X    n = 0;
  1255. X    tunerBrowser = XmCreateScrolledList(form, "tuner", args, n);
  1256. X    XtAddCallback(tunerBrowser, XmNbrowseSelectionCallback, cb_tuner, 0);
  1257. X    XtManageChild(tunerBrowser);
  1258. X
  1259. X#ifdef VOLUME
  1260. X
  1261. X    labelVolume = LABEL(args, n, "labelVolume", form);
  1262. X    
  1263. X    n = 0;
  1264. X    volumeSlider = XtCreateManagedWidget("volume", xmScrollBarWidgetClass,
  1265. X                       form, args, n);
  1266. X    XtAddCallback(volumeSlider, XmNvalueChangedCallback, cb_volume, 0);
  1267. X    show_volume(getvolume());
  1268. X#endif /* VOLUME */
  1269. X
  1270. X    n = 0;
  1271. X    muteButton = XtCreateManagedWidget("mute", xmToggleButtonWidgetClass,
  1272. X                       form, args, n);
  1273. X    XtAddCallback(muteButton, XmNvalueChangedCallback, cb_mute, 0);
  1274. X
  1275. X    n = 0;
  1276. X    revertButton = XtCreateManagedWidget("revert", xmPushButtonWidgetClass,
  1277. X                     form, args, n);
  1278. X    XtAddCallback(revertButton, XmNactivateCallback, cb_revert, 0);
  1279. X
  1280. X    n = 0;
  1281. X    okButton = XtCreateManagedWidget("OK", xmPushButtonWidgetClass,
  1282. X                     form, args, n);
  1283. X    XtAddCallback(okButton, XmNactivateCallback, cb_ok, 0);
  1284. X
  1285. X#ifdef ANP_COMMAND
  1286. X    n = 0;
  1287. X    anpButton = XtCreateManagedWidget("anp", xmToggleButtonWidgetClass,
  1288. X                       form, args, n);
  1289. X    XtAddCallback(anpButton, XmNvalueChangedCallback, cb_anp, 0);
  1290. X#endif /* ANP_COMMAND */
  1291. X
  1292. X    n = 0;
  1293. X    radioButton = XtCreateManagedWidget("radio", xmPushButtonWidgetClass,
  1294. X                     form, args, n);
  1295. X    XtAddCallback(radioButton, XmNactivateCallback, cb_radio, 0);
  1296. X}
  1297. X
  1298. static void
  1299. cb_playlist(w, udata, wdata)
  1300. X    Widget *w;
  1301. X    XmListCallbackStruct *wdata;
  1302. X    void *udata;
  1303. X{
  1304. X    XmListDeselectAllItems(playlistBrowser);
  1305. X} 
  1306. X
  1307. static void
  1308. cb_tuner(w, udata, wdata)
  1309. X    Widget *w;
  1310. X    XmListCallbackStruct *wdata;
  1311. X    void *udata;
  1312. X{
  1313. X    prev_pos = tuner_pos;
  1314. X    tuner_pos = wdata->item_position;
  1315. X    do_tune(tuner_pos);
  1316. X} 
  1317. X
  1318. static void
  1319. cb_mute(w, udata, wdata)
  1320. X    Widget *w;
  1321. X    XmToggleButtonCallbackStruct *wdata;
  1322. X    void *udata;
  1323. X{
  1324. X    do_mute(wdata->set);
  1325. X}
  1326. X
  1327. static void
  1328. cb_details(w, udata, wdata)
  1329. X    Widget *w;
  1330. X    void *wdata;
  1331. X    void *udata;
  1332. X{
  1333. X}
  1334. X
  1335. static void
  1336. cb_revert(w, udata, wdata)
  1337. X    Widget *w;
  1338. X    void *wdata;
  1339. X    void *udata;
  1340. X{
  1341. X    int i;
  1342. X
  1343. X    i = prev_pos;
  1344. X    prev_pos = tuner_pos;
  1345. X    tuner_pos = i;
  1346. X    do_tune(tuner_pos);
  1347. X}
  1348. X
  1349. static void
  1350. cb_ok(w, udata, wdata)
  1351. X    Widget *w;
  1352. X    void *wdata;
  1353. X    void *udata;
  1354. X{
  1355. X    exit(0);
  1356. X}
  1357. X
  1358. X#ifdef ANP_COMMAND
  1359. int anp_pid = -1;
  1360. XFILE *anp_fp;
  1361. XXtInputId anp_id;
  1362. X
  1363. static void
  1364. cb_anpdone()
  1365. X{
  1366. X    do_mute(0);
  1367. X    anp_pid = -1;
  1368. X    pclose(anp_fp);
  1369. X    XtRemoveInput(anp_id);
  1370. X}
  1371. X
  1372. static void
  1373. cb_anp(w, udata, wdata)
  1374. X    Widget *w;
  1375. X    XmToggleButtonCallbackStruct *wdata;
  1376. X    void *udata;
  1377. X{
  1378. X    char dbuf[10];
  1379. X    
  1380. X    if ( wdata->set ) {
  1381. X    if ( anp_pid > 0) {
  1382. X        fprintf(stderr, "tuner: anp already active\n");
  1383. X        return;
  1384. X    }
  1385. X    do_mute(1);
  1386. X    if ( (anp_fp=popen(ANP_COMMAND, "r")) == NULL ) {
  1387. X        perror(ANP_COMMAND);
  1388. X        return;
  1389. X    }
  1390. X    if ( fgets(dbuf, 10, anp_fp) == NULL
  1391. X                    || sscanf(dbuf, "%d", &anp_pid) != 1) {
  1392. X        fprintf(stderr, "tuner: anp command did not give pid\n");
  1393. X        fclose(anp_fp);
  1394. X        anp_pid = -1;
  1395. X        return;
  1396. X    }
  1397. X    anp_id = XtAddInput(fileno(anp_fp), XtInputReadMask, cb_anpdone, 0);
  1398. X    } else {
  1399. X    if ( anp_pid < 0 ) {
  1400. X        fprintf(stderr, "tuner: anp not active\n");
  1401. X        return;
  1402. X    }
  1403. X    if ( kill(anp_pid, SIGTERM) < 0 ) {
  1404. X        fprintf(stderr, "kill %d:", anp_pid);
  1405. X        perror("");
  1406. X    }    
  1407. X    cb_anpdone();
  1408. X    }
  1409. X}
  1410. X#endif /* ANP_COMMAND */
  1411. X
  1412. static void
  1413. cb_radio(w, udata, wdata)
  1414. X    Widget *w;
  1415. X    void *wdata;
  1416. X    void *udata;
  1417. X{
  1418. X    system(RADIO_COMMAND);
  1419. X}
  1420. X
  1421. X#ifdef VOLUME
  1422. static void
  1423. cb_volume(w, udata, wdata)
  1424. X    Widget *w;
  1425. X    XmScrollBarCallbackStruct *wdata;
  1426. X    void *udata;
  1427. X{
  1428. X    setvolume(wdata->value);
  1429. X}
  1430. X
  1431. void
  1432. show_volume(value)
  1433. X    int value;
  1434. X{
  1435. X    Arg args[2];
  1436. X    int n;
  1437. X
  1438. X    n = 0;
  1439. X    XtSetArg(args[n], XmNvalue, value); n++;
  1440. X    XtSetValues(volumeSlider, args, n);
  1441. X}
  1442. X#endif /* VOLUME */
  1443. X
  1444. X/*
  1445. X** show_tune - Show which station we're tuned to
  1446. X*/
  1447. void
  1448. show_tune(station, name, playing, since, mute)
  1449. X    int station;
  1450. X    char *name, *playing, *since;
  1451. X    int mute;
  1452. X{
  1453. X    Arg args[2];
  1454. X    int n;
  1455. X    XmString str;
  1456. X    
  1457. X    XmListDeselectAllItems(tunerBrowser);
  1458. X    if ( station ) {
  1459. X      XmListSelectPos(tunerBrowser, station, 0);
  1460. X      if ( prev_pos == 0 )
  1461. X    prev_pos = station;
  1462. X  }
  1463. X
  1464. X    n = 0;
  1465. X    str = XmStringCreateLtoR(name, XmSTRING_DEFAULT_CHARSET);
  1466. X    XtSetArg(args[n], XmNlabelString, str); n++;
  1467. X    XtSetValues(currentStation, args, n);
  1468. X    
  1469. X    n = 0;
  1470. X    str = XmStringCreateLtoR(playing, XmSTRING_DEFAULT_CHARSET);
  1471. X    XtSetArg(args[n], XmNlabelString, str); n++;
  1472. X    XtSetValues(currentPlaying, args, n);
  1473. X    
  1474. X    n = 0;
  1475. X    str = XmStringCreateLtoR(since, XmSTRING_DEFAULT_CHARSET);
  1476. X    XtSetArg(args[n], XmNlabelString, str); n++;
  1477. X    XtSetValues(currentTime, args, n);
  1478. X
  1479. X    n = 0;
  1480. X    XtSetArg(args[n], XmNset, mute); n++;
  1481. X    XtSetValues(muteButton, args, n);
  1482. X    
  1483. X}
  1484. X
  1485. X/*
  1486. X** show_stations - Show new station list.
  1487. X*/
  1488. static void
  1489. new_browser(browser, slist, nitems)
  1490. X    Widget browser;
  1491. X    char **slist;
  1492. X    int nitems;
  1493. X{
  1494. X    XmString *list;
  1495. X    int i;
  1496. X
  1497. X    /* XXX Should we free old items here? */
  1498. X    XmListDeselectAllItems(browser);
  1499. X#ifndef MOTIF1_0
  1500. X    XmListDeleteAllItems(browser);
  1501. X#else
  1502. X    {
  1503. X    Arg args[1];
  1504. X    XtSetArg(args[0], XmNitemCount, NULL);
  1505. X    XtGetValues(browser, args, 1);
  1506. X    for(i=0; i<(int)args[0].value; i++)
  1507. X      XmListDeletePos(browser, 1);
  1508. X    }
  1509. X#endif
  1510. X    list = (XmString *)XtMalloc(sizeof(XmString)*nitems);
  1511. X    for ( i=0; i<nitems; i++)
  1512. X    list[i] = XmStringCreate(slist[i], XmSTRING_DEFAULT_CHARSET);
  1513. X#ifdef MOTIF1_0
  1514. X    for (i=0; i<nitems; i++)
  1515. X      XmListAddItem(browser, list[i], i+1);
  1516. X#else
  1517. X    XmListAddItems(browser, list, nitems, 0);
  1518. X#endif
  1519. X    for ( i=0; i<nitems; i++) {
  1520. X        XtFree(list[i]);
  1521. X
  1522. X    }
  1523. X    XtFree(list);
  1524. X}
  1525. X
  1526. void
  1527. show_tuner(slist, nitems)
  1528. X    char **slist;
  1529. X    int nitems;
  1530. X{
  1531. X    new_browser(tunerBrowser, slist, nitems);
  1532. X}
  1533. X
  1534. void
  1535. show_playlist(slist, nitems, col)
  1536. X    char **slist;
  1537. X    int nitems;
  1538. X{
  1539. X    static Arg arg[1];
  1540. X
  1541. X    new_browser(playlistBrowser, slist, nitems);
  1542. X    XmListSetBottomPos(playlistBrowser, 0);
  1543. X    XtSetArg(arg[0], XmNforeground, 0);
  1544. X    if ( col ) {
  1545. X    XtGetValues(labelCurrent, arg, 1);
  1546. X    } else {
  1547. X    XtGetValues(labelTuner, arg, 1);
  1548. X    }
  1549. X    XtSetValues(labelPlaylist, arg, 1);
  1550. X}
  1551. X
  1552. watch_socket(sock, cback)
  1553. X    int sock;
  1554. X    int (*cback)();
  1555. X{
  1556. X    (void)XtAddInput(sock, XtInputReadMask, cback, 0);
  1557. X}
  1558. END_OF_FILE
  1559. if test 8557 -ne `wc -c <'tuner_ui.c'`; then
  1560.     echo shar: \"'tuner_ui.c'\" unpacked with wrong size!
  1561. fi
  1562. # end of 'tuner_ui.c'
  1563. fi
  1564. if test -f 'tuner_volume.c' -a "${1}" != "-c" ; then 
  1565.   echo shar: Will not clobber existing file \"'tuner_volume.c'\"
  1566. else
  1567. echo shar: Extracting \"'tuner_volume.c'\" \(481 characters\)
  1568. sed "s/^X//" >'tuner_volume.c' <<'END_OF_FILE'
  1569. X#include "tuner.h"
  1570. X
  1571. X#ifdef VOLUME
  1572. X
  1573. X#include <audio.h>
  1574. X
  1575. setvolume(value)
  1576. X    int value;
  1577. X{
  1578. X    long par[4];
  1579. X
  1580. X    par[0] = AL_LEFT_SPEAKER_GAIN;
  1581. X    par[1] = value;
  1582. X    par[2] = AL_RIGHT_SPEAKER_GAIN;
  1583. X    par[3] = value;
  1584. X    ALsetparams(AL_DEFAULT_DEVICE, par, 4);
  1585. X}
  1586. X
  1587. getvolume()
  1588. X{
  1589. X    long par[4];
  1590. X    int value;
  1591. X
  1592. X    par[0] = AL_LEFT_SPEAKER_GAIN;
  1593. X    par[2] = AL_RIGHT_SPEAKER_GAIN;
  1594. X    ALgetparams(AL_DEFAULT_DEVICE, par, 4);
  1595. X    return (par[1]+par[3]) / 2;
  1596. X}
  1597. X#endif /* VOLUME */
  1598. END_OF_FILE
  1599. if test 481 -ne `wc -c <'tuner_volume.c'`; then
  1600.     echo shar: \"'tuner_volume.c'\" unpacked with wrong size!
  1601. fi
  1602. # end of 'tuner_volume.c'
  1603. fi
  1604. echo shar: End of archive 1 \(of 1\).
  1605. cp /dev/null ark1isdone
  1606. MISSING=""
  1607. for I in 1 ; do
  1608.     if test ! -f ark${I}isdone ; then
  1609.     MISSING="${MISSING} ${I}"
  1610.     fi
  1611. done
  1612. if test "${MISSING}" = "" ; then
  1613.     echo You have the archive.
  1614.     rm -f ark[1-9]isdone
  1615. else
  1616.     echo You still need to unpack the following archives:
  1617.     echo "        " ${MISSING}
  1618. fi
  1619. ##  End of shell archive.
  1620. exit 0
  1621.